package com.carey.blog.event.ping;

import java.net.URL;
import java.net.URLEncoder;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.lang.StringUtils;
import org.json.JSONObject;

import com.carey.blog.event.EventTypes;
import com.carey.blog.framework.latke.event.AbstractEventListener;
import com.carey.blog.framework.latke.event.Event;
import com.carey.blog.framework.latke.event.EventException;
import com.carey.blog.framework.latke.event.EventManager;
import com.carey.blog.model.Article;
import com.carey.blog.model.Preference;
import com.carey.blog.util.Preferences;
import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.appengine.api.urlfetch.URLFetchServiceFactory;

/**
 * This listener is responsible for pinging <a
 * href="http://blogsearch.google.com"> Google Blog Search Service</a>
 * asynchronously while updating an article.
 * 
 * <p>
 * <li>
 * <a href="http://www.google.com/help/blogsearch/pinging_API.html"> About
 * Google Blog Search Pinging Service API</a></li>
 * </p>
 * 
 * @see AddArticleGoogleBlogSearchPinger
 */
public final class UpdateArticleGoogleBlogSearchPinger extends
		AbstractEventListener<JSONObject> {

	/**
	 * Logger.
	 */
	private static final Logger LOGGER = Logger
			.getLogger(UpdateArticleGoogleBlogSearchPinger.class.getName());
	/**
	 * URL fetch service.
	 */
	private static final URLFetchService URL_FETCH_SERVICE = URLFetchServiceFactory
			.getURLFetchService();
	/**
	 * Preference utilities.
	 */
	private Preferences preferenceUtils = Preferences.getInstance();

	/**
	 * Constructs a {@link UpdateArticleGoogleBlogSearchPinger} object with the
	 * specified event manager.
	 * 
	 * @param eventManager
	 *            the specified event manager
	 */
	public UpdateArticleGoogleBlogSearchPinger(final EventManager eventManager) {
		super(eventManager);
	}

	/**
	 * Gets the event type {@linkplain EventTypes#UPDATE_ARTICLE}.
	 * 
	 * @return event type
	 */
	@Override
	public String getEventType() {
		return EventTypes.UPDATE_ARTICLE;
	}

	@Override
	public void action(final Event<JSONObject> event) throws EventException {
		final JSONObject eventData = event.getData();

		String articleTitle = null;
		try {
			final JSONObject article = eventData.getJSONObject(Article.ARTICLE);
			articleTitle = article.getString(Article.ARTICLE_TITLE);
			final JSONObject preference = preferenceUtils.getPreference();
			final String blogTitle = preference
					.getString(Preference.BLOG_TITLE);
			String blogHost = preference.getString(Preference.BLOG_HOST)
					.toLowerCase().trim();
			if ("localhost".equals(blogHost.split(":")[0].trim())) {
				LOGGER.log(
						Level.INFO,
						"Carey Blog runs on local server, so should not ping "
								+ "Google Blog Search Service for the article[title={0}]",
						new Object[] { article.getString(Article.ARTICLE_TITLE) });
				return;
			}
			blogHost = StringUtils.removeEnd("http://" + blogHost, "/");

			final String articlePermalink = blogHost
					+ article.getString(Article.ARTICLE_PERMALINK);
			final String spec = "http://blogsearch.google.com/ping?name="
					+ URLEncoder.encode(blogTitle, "UTF-8") + "&url="
					+ URLEncoder.encode(blogHost, "UTF-8") + "&changesURL="
					+ URLEncoder.encode(articlePermalink, "UTF-8");
			LOGGER.log(Level.FINER,
					"Request Google Blog Search Service API[{0}] while updateing "
							+ "an article[title=" + articleTitle + "]", spec);
			URL_FETCH_SERVICE.fetchAsync(new URL(spec));
		} catch (final Exception e) {
			LOGGER.log(Level.SEVERE,
					"Ping Google Blog Search Service fail while updating an "
							+ "article[title=" + articleTitle + "]", e);
		}
	}
}
